using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Framework.Interface;
using Framework.Singleton;
using UnityEngine;

public class EventsManager : Singleton<EventsManager>, IManager
{
    private Dictionary<Type, List<Action<IListener>>> events = new Dictionary<Type, List<Action<IListener>>>();
    
    public async UniTask Initialize()
    {
        await UniTask.CompletedTask;
        events.Clear();
    }

    public void Shutdown()
    {
        events.Clear();
    }

    public void Add<T>(Action<IListener> listener) where T : IListener
    {
        Type type = typeof(T);

        if (events.TryGetValue(type, out List<Action<IListener>> listeners))
        {
            if (listeners.Contains(listener))
            {
                Debug.LogError($"evt \"{type.Name}\" has been added, should not be added again.");
                return;
            }
            
            listeners.Add(listener);
        }
        else
        {
            listeners = new List<Action<IListener>>() { listener };
            events.Add(type, listeners);
        }
    }

    public void Remove<T>(Action<IListener> listener) where T : IListener
    {
        Type type = typeof(T);

        if (events.TryGetValue(type, out List<Action<IListener>> listeners))
        {
            if (!listeners.Contains(listener))
            {
                Debug.LogError($"evt \"{type.Name}\" has not been added, should be added before being removed.");
                return;
            }

            listeners.Remove(listener);

            if (listeners.Count <= 0)
                events.Remove(type);
        }
        else
        {
            // Debug.Log($"evt \"{type.Name}\" has not been added, should be added before being removed.");
        }
    }

    public void Broadcast(IListener evtArgs)
    {
        Type type = evtArgs.GetType();

        if (events.TryGetValue(type, out List<Action<IListener>> listeners))
        {
            if (listeners.Count <= 0)
            {
                Debug.LogError($"evt \"{type.Name}\" has not add any listener yet.");
                return;
            }
            
            listeners.ForEach(one => one(evtArgs));
        }
        else
        {
            Debug.Log($"evt \"{type.Name}\" has not add any listener yet.");
        }
    }

    public void RemoveAll()
    {
        events.Clear();
    }
}
